{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# 面向对象进阶"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## @property\n",
    "装饰器如果想访问属性可以通过属性的getter（访问器）和setter（修改器）方法进行对应的操作。\n",
    "如果要做到这点，就可以考虑使用@property包装器来包装getter和setter方法"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "小明已经完成义务教育\n",
      "小明正在上小学\n"
     ]
    },
    {
     "ename": "AttributeError",
     "evalue": "can't set attribute 'name'",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mAttributeError\u001B[0m                            Traceback (most recent call last)",
      "Cell \u001B[1;32mIn[4], line 30\u001B[0m\n\u001B[0;32m     28\u001B[0m person\u001B[38;5;241m.\u001B[39mage \u001B[38;5;241m=\u001B[39m \u001B[38;5;241m11\u001B[39m\n\u001B[0;32m     29\u001B[0m person\u001B[38;5;241m.\u001B[39mplay()\n\u001B[1;32m---> 30\u001B[0m person\u001B[38;5;241m.\u001B[39mname \u001B[38;5;241m=\u001B[39m \u001B[38;5;124m'\u001B[39m\u001B[38;5;124m小红\u001B[39m\u001B[38;5;124m'\u001B[39m\n\u001B[0;32m     31\u001B[0m person\u001B[38;5;241m.\u001B[39mplay()\n",
      "\u001B[1;31mAttributeError\u001B[0m: can't set attribute 'name'"
     ]
    }
   ],
   "source": [
    "class Person(object):\n",
    "    def __init__(self, name, age):\n",
    "        \"\"\"构造方法\"\"\"\n",
    "        self._name = name\n",
    "        self._age = age\n",
    "    # 访问器，getter方法\n",
    "    @property\n",
    "    def name(self):\n",
    "        return self._name\n",
    "\n",
    "    @property\n",
    "    def age(self):\n",
    "        return self._age\n",
    "\n",
    "    # 修改器，setter方法\n",
    "    @age.setter\n",
    "    def age(self, age):\n",
    "        self._age = age\n",
    "\n",
    "    def play(self):\n",
    "        if  self._age <= 16:\n",
    "            print(\"%s正在上小学\" % self._name)\n",
    "        else:\n",
    "            print(\"%s已经完成义务教育\" % self._name)\n",
    "\n",
    "person = Person('小明', 19)\n",
    "person.play()\n",
    "person.age = 11\n",
    "person.play()\n",
    "person.name = '小红'\n",
    "person.play()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## __slots__魔法\n",
    "Python允许我们在程序运行时给对象绑定新的属性或方法，当然也可以对已经绑定的属性和方法进行解绑定。\n",
    "但是如果我们需要限定自定义类型的对象只能绑定某些属性，可以通过在类中定义__slots__变量来进行限定。\n",
    "需要注意的是__slots__的限定只对当前类的对象生效，对子类并不起任何作用"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "小明已经完成义务教育\n",
      "小明正在上小学\n"
     ]
    },
    {
     "ename": "AttributeError",
     "evalue": "'Person' object has no attribute '_is_gay'",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mAttributeError\u001B[0m                            Traceback (most recent call last)",
      "Cell \u001B[1;32mIn[10], line 33\u001B[0m\n\u001B[0;32m     31\u001B[0m person\u001B[38;5;241m.\u001B[39mplay()\n\u001B[0;32m     32\u001B[0m person\u001B[38;5;241m.\u001B[39m_gender \u001B[38;5;241m=\u001B[39m \u001B[38;5;124m'\u001B[39m\u001B[38;5;124m男\u001B[39m\u001B[38;5;124m'\u001B[39m\n\u001B[1;32m---> 33\u001B[0m person\u001B[38;5;241m.\u001B[39m_is_gay \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mFalse\u001B[39;00m\n",
      "\u001B[1;31mAttributeError\u001B[0m: 'Person' object has no attribute '_is_gay'"
     ]
    }
   ],
   "source": [
    "class Person(object):\n",
    "    __slots__ = ('_name', '_age', '_gender')\n",
    "\n",
    "    def __init__(self, name, age):\n",
    "        \"\"\"构造方法\"\"\"\n",
    "        self._name = name\n",
    "        self._age = age\n",
    "    # 访问器，getter方法\n",
    "    @property\n",
    "    def name(self):\n",
    "        return self._name\n",
    "\n",
    "    @property\n",
    "    def age(self):\n",
    "        return self._age\n",
    "\n",
    "    # 修改器，setter方法\n",
    "    @age.setter\n",
    "    def age(self, age):\n",
    "        self._age = age\n",
    "\n",
    "    def play(self):\n",
    "        if  self._age <= 16:\n",
    "            print(\"%s正在上小学\" % self._name)\n",
    "        else:\n",
    "            print(\"%s已经完成义务教育\" % self._name)\n",
    "\n",
    "person = Person('小明', 19)\n",
    "person.play()\n",
    "person.age = 11\n",
    "person.play()\n",
    "person._gender = '男'\n",
    "person._is_gay = False"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 静态方法和类方法\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "12\n",
      "6.0\n",
      "12\n",
      "6.0\n"
     ]
    }
   ],
   "source": [
    "from math import sqrt\n",
    "\n",
    "\n",
    "class Triangle(object):\n",
    "    def __init__(self, a, b, c):\n",
    "        \"\"\"构造方法\"\"\"\n",
    "        self._a = a\n",
    "        self._b = b\n",
    "        self._c = c\n",
    "\n",
    "    @staticmethod\n",
    "    def is_valid(a, b, c):\n",
    "        return a + b > c and b + c > a and a + c > b\n",
    "\n",
    "    def perimeter(self):\n",
    "        \"\"\"周长\"\"\"\n",
    "        return self._a + self._b + self._c\n",
    "\n",
    "    def area(self):\n",
    "        \"\"\"面积\"\"\"\n",
    "        half = self.perimeter() / 2\n",
    "        return sqrt(half * (half - self._a) * (half - self._b) * (half - self._c))\n",
    "\n",
    "a, b, c = 3, 4, 5\n",
    "if Triangle.is_valid(a, b, c):\n",
    "    # 静态方法与类方法直接通过类名调用\n",
    "    t = Triangle(a, b, c)\n",
    "    print(t.perimeter())\n",
    "    print(t.area())\n",
    "    # 对象方法也可以通过类名调用，但是需要传入所属对象作为第一个参数\n",
    "    print(Triangle.perimeter(t))\n",
    "    print(Triangle.area(t))\n",
    "else:\n",
    "    print('无法构成三角形')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "和静态方法比较类似，Python还可以在类中定义类方法，\n",
    "类方法的第一个参数约定名为cls，它代表的是当前类相关的信息的对象（类本身也是一个对象，有的地方也称之为类的元数据对象），\n",
    "通过这个参数我们可以获取和类相关的信息并且可以创建出类的对象，代码如下所示。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "17:40:07\n",
      "17:40:08\n",
      "17:40:09\n",
      "17:40:10\n",
      "17:40:11\n",
      "17:40:12\n",
      "17:40:13\n",
      "17:40:14\n",
      "17:40:15\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mKeyboardInterrupt\u001B[0m                         Traceback (most recent call last)",
      "Cell \u001B[1;32mIn[14], line 40\u001B[0m\n\u001B[0;32m     38\u001B[0m \u001B[38;5;28;01mwhile\u001B[39;00m \u001B[38;5;28;01mTrue\u001B[39;00m:\n\u001B[0;32m     39\u001B[0m     \u001B[38;5;28mprint\u001B[39m(clock\u001B[38;5;241m.\u001B[39mshow())\n\u001B[1;32m---> 40\u001B[0m     \u001B[43msleep\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;241;43m1\u001B[39;49m\u001B[43m)\u001B[49m\n\u001B[0;32m     41\u001B[0m     clock\u001B[38;5;241m.\u001B[39mrun()\n",
      "\u001B[1;31mKeyboardInterrupt\u001B[0m: "
     ]
    }
   ],
   "source": [
    "from time import time, localtime, sleep\n",
    "\n",
    "\n",
    "class Clock(object):\n",
    "    \"\"\"数字时钟\"\"\"\n",
    "\n",
    "    def __init__(self, hour=0, minute=0, second=0):\n",
    "        self._hour = hour\n",
    "        self._minute = minute\n",
    "        self._second = second\n",
    "\n",
    "    @classmethod\n",
    "    def now(cls):\n",
    "        ctime = localtime(time())\n",
    "        return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)\n",
    "\n",
    "    def run(self):\n",
    "        \"\"\"走字\"\"\"\n",
    "        self._second += 1\n",
    "        if self._second == 60:\n",
    "            self._second = 0\n",
    "            self._minute += 1\n",
    "            if self._minute == 60:\n",
    "                self._minute = 0\n",
    "                self._hour += 1\n",
    "                if self._hour == 24:\n",
    "                    self._hour = 0\n",
    "\n",
    "    def show(self):\n",
    "        \"\"\"显示时间\"\"\"\n",
    "        return '%02d:%02d:%02d' % \\\n",
    "               (self._hour, self._minute, self._second)\n",
    "\n",
    "\n",
    "\n",
    "# 通过类方法创建对象并获取系统时间\n",
    "clock = Clock.now()\n",
    "while True:\n",
    "    print(clock.show())\n",
    "    sleep(1)\n",
    "    clock.run()\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 继承\n",
    "在已有类的基础上创建新类，这其中的一种做法就是让一个类从另一个类那里将属性和方法直接继承下来，从而减少重复代码的编写。\n",
    "提供继承信息的我们称之为父类，也叫超类或基类；得到继承信息的我们称之为子类，也叫派生类或衍生类。\n",
    "子类除了继承父类提供的属性和方法，还可以定义自己特有的属性和方法"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "七年级的小明正在学习物理.\n",
      "小明只能观看《熊出没》.\n",
      "张三教授正在讲操作系统\n",
      "张三正在观看爱情动作片.\n"
     ]
    }
   ],
   "source": [
    "class Person(object):\n",
    "    \"\"\"人\"\"\"\n",
    "\n",
    "    def __init__(self, name, age):\n",
    "        self._name = name\n",
    "        self._age = age\n",
    "\n",
    "    @property\n",
    "    def name(self):\n",
    "        return self._name\n",
    "\n",
    "    @property\n",
    "    def age(self):\n",
    "        return self._age\n",
    "\n",
    "    @age.setter\n",
    "    def age(self, age):\n",
    "        self._age = age\n",
    "\n",
    "    def play(self):\n",
    "        print('%s正在愉快的玩耍.' % self._name)\n",
    "\n",
    "    def watch_av(self):\n",
    "        if self._age >= 18:\n",
    "            print('%s正在观看爱情动作片.' % self._name)\n",
    "        else:\n",
    "            print('%s只能观看《熊出没》.' % self._name)\n",
    "\n",
    "\n",
    "class Student(Person):\n",
    "    \"\"\"学生\"\"\"\n",
    "\n",
    "    def __init__(self, name, age, grade):\n",
    "        super().__init__(name, age)\n",
    "        self._grade = grade\n",
    "\n",
    "    @property\n",
    "    def grade(self):\n",
    "        return self._grade\n",
    "\n",
    "    @grade.setter\n",
    "    def grade(self, grade):\n",
    "        self._grade = grade\n",
    "\n",
    "    def study(self, course):\n",
    "        print('%s的%s正在学习%s.' % (self._grade, self._name, course))\n",
    "\n",
    "\n",
    "class Teacher(Person):\n",
    "    \"\"\"教师\"\"\"\n",
    "\n",
    "    def __init__(self, name, age, title):\n",
    "        super().__init__(name, age)\n",
    "        self._title = title\n",
    "\n",
    "    @property\n",
    "    def title(self):\n",
    "        return self._title\n",
    "\n",
    "    @title.setter\n",
    "    def title(self, title):\n",
    "        self._title = title\n",
    "\n",
    "    def teach(self, course):\n",
    "        print(\"%s%s正在讲%s\" % (self._name, self._title, course))\n",
    "\n",
    "stu = Student(\"小明\", 13, '七年级')\n",
    "stu.study('物理')\n",
    "stu.watch_av()\n",
    "teacher = Teacher(\"张三\", 30, \"教授\")\n",
    "teacher.teach(\"操作系统\")\n",
    "teacher.watch_av()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 多态\n",
    "子类在继承了父类的方法后，可以对父类已有的方法给出新的实现版本，这个动作称之为方法重写（override）。\n",
    "通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本，当我们调用这个经过子类重写的方法时，不同的子类对象会表现出不同的行为，这个就是多态（poly-morphism）。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "旺财: 汪汪汪...\n",
      "小丽: 喵喵喵...\n",
      "小黑: 汪汪汪...\n"
     ]
    }
   ],
   "source": [
    "from abc import abstractmethod, ABCMeta\n",
    "\n",
    "\n",
    "class Pet(object, metaclass=ABCMeta):\n",
    "    \"\"\"宠物\"\"\"\n",
    "    def __init__(self, nickname):\n",
    "        self._nickname = nickname\n",
    "\n",
    "    # 抽象方法\n",
    "    @abstractmethod\n",
    "    def make_voice(self):\n",
    "        \"\"\"发出声音\"\"\"\n",
    "        pass\n",
    "\n",
    "class Dog(Pet):\n",
    "    \"\"\"狗\"\"\"\n",
    "\n",
    "    def make_voice(self):\n",
    "        print(\"%s: 汪汪汪...\" % self._nickname)\n",
    "\n",
    "class Cat(Pet):\n",
    "    \"\"\"猫\"\"\"\n",
    "\n",
    "    def make_voice(self):\n",
    "        print(\"%s: 喵喵喵...\" % self._nickname)\n",
    "\n",
    "pets = [Dog('旺财'), Cat('小丽'), Dog('小黑')]\n",
    "for pet in pets:\n",
    "    pet.make_voice()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "在上面的代码中，我们将Pet类处理成了一个抽象类，所谓抽象类就是不能够创建对象的类，这种类的存在就是专门为了让其他类去继承它。Python从语法层面并没有像Java或C#那样提供对抽象类的支持，但是我们可以通过abc模块的ABCMeta元类和abstractmethod包装器来达到抽象类的效果，如果一个类中存在抽象方法那么这个类就不能够实例化（创建对象）。上面的代码中，Dog和Cat两个子类分别对Pet类中的make_voice抽象方法进行了重写并给出了不同的实现版本，当我们在main函数中调用该方法时，这个方法就表现出了多态行为（同样的方法做了不同的事情）。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## __dict__\n",
    "在 Python 类的内部，无论是类属性还是实例属性，都是以字典的形式进行存储的，其中属性名作为键，而值作为该键对应的值。\n",
    "该属性可以用类名或者类的实例对象来调用，用类名直接调用 __dict__，会输出该由类中所有类属性组成的字典；\n",
    "而使用类的实例对象调用 __dict__，会输出由类中所有实例属性组成的字典。\n",
    "对于具有继承关系的父类和子类来说，父类有自己的 __dict__，同样子类也有自己的 __dict__，它不会包含父类的 __dict__。\n",
    "除此之外，借助由类实例对象调用 __dict__ 属性获取的字典，可以使用字典的方式对其中实例属性的值进行修改"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'__module__': '__main__', 'name': 'yzpang', 'age': 34, '__init__': <function Storage.__init__ at 0x00000187CDD3B010>, '__dict__': <attribute '__dict__' of 'Storage' objects>, '__weakref__': <attribute '__weakref__' of 'Storage' objects>, '__doc__': None}\n",
      "{'address': 'hefei'}\n",
      "{'address': 'fuyang'}\n"
     ]
    }
   ],
   "source": [
    "class Storage(object):\n",
    "    name = 'yzpang'\n",
    "    age = 34\n",
    "    def __init__(self):\n",
    "        self.address = 'hefei'\n",
    "\n",
    "\n",
    "sample = Storage()\n",
    "print(Storage.__dict__)\n",
    "print(sample.__dict__)\n",
    "sample.__dict__['address'] = 'fuyang'\n",
    "print(sample.__dict__)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## __dir__\n",
    "通过此函数可以某个对象拥有的所有的属性名和方法名，该函数会返回一个包含有所有属性名和方法名的有序列表。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [
    {
     "data": {
      "text/plain": "['address',\n '__module__',\n 'name',\n 'age',\n '__init__',\n '__dict__',\n '__weakref__',\n '__doc__',\n '__new__',\n '__repr__',\n '__hash__',\n '__str__',\n '__getattribute__',\n '__setattr__',\n '__delattr__',\n '__lt__',\n '__le__',\n '__eq__',\n '__ne__',\n '__gt__',\n '__ge__',\n '__reduce_ex__',\n '__reduce__',\n '__subclasshook__',\n '__init_subclass__',\n '__format__',\n '__sizeof__',\n '__dir__',\n '__class__']"
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "class Storage(object):\n",
    "    name = 'yzpang'\n",
    "    age = 34\n",
    "    def __init__(self):\n",
    "        self.address = 'hefei'\n",
    "\n",
    "sample = Storage()\n",
    "dir(sample)\n",
    "\n",
    "# 调用内部__dir__方法\n",
    "sample.__dir__()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## __repr__\n",
    "当我们输出某个实例化对象时，其调用的就是该对象的 __repr__() 方法，输出的是该方法的返回值。\n",
    "默认情况下，__repr__() 会返回和调用者有关的 “类名+object at+内存地址”信息: <__main__.CLanguage object at 0x000001A7275221D0>\n",
    "我们还可以通过在类中重写这个方法，从而实现当输出实例化对象时，输出我们想要的信息。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Storage[name=yzpang,age=34,address=hefei]\n"
     ]
    }
   ],
   "source": [
    "class Storage(object):\n",
    "    name = 'yzpang'\n",
    "    age = 34\n",
    "    def __init__(self):\n",
    "        self.address = 'hefei'\n",
    "\n",
    "    def __repr__(self):\n",
    "        return \"Storage[name=\" + self.name + \",age=\" + str(self.age) + \",address=\" + self.address + \"]\"\n",
    "\n",
    "sample = Storage()\n",
    "\n",
    "print(sample)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## __new__\n",
    "__new__() 是一种负责创建类实例的静态方法，它无需使用 staticmethod 装饰器修饰，且该方法会优先 __init__() 初始化方法被调用。\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "__new__(): <class '__main__.DemoClass'> ('abc',) {}\n",
      "__init__(): <__main__.DemoClass object at 0x00000187CFE32EF0> abc\n",
      "__new__(): <class '__main__.DemoClass'> ('xyz',) {}\n",
      "__init__(): <__main__.DemoClass object at 0x00000187CFE30160> xyz\n",
      "__init__()\n",
      "<class '__main__.NonZero'>\n",
      "<class 'NoneType'>\n"
     ]
    }
   ],
   "source": [
    "class DemoClass(object):\n",
    "    instances_created = 0\n",
    "    def __new__(cls, *args, **kwargs):\n",
    "        print(\"__new__():\", cls, args, kwargs)\n",
    "        instance = super().__new__(cls)\n",
    "        instance.number = cls.instances_created\n",
    "        cls.instances_created += 1\n",
    "        return instance\n",
    "\n",
    "    def __init__(self, attribute):\n",
    "        print(\"__init__():\", self, attribute)\n",
    "        self.attribute = attribute\n",
    "\n",
    "demo1 = DemoClass(\"abc\")\n",
    "demo2 = DemoClass(\"xyz\")\n",
    "\n",
    "# print(demo1.instance.number, demo1.instances_created)\n",
    "# print(demo2.instance.number, demo2.instances_created)\n",
    "\n",
    "class NonZero(int):\n",
    "    def __new__(cls,value):\n",
    "        return super().__new__(cls,value) if value != 0 else None\n",
    "    def __init__(self,skipped_value):\n",
    "        #此例中会跳过此方法\n",
    "        print(\"__init__()\")\n",
    "        super().__init__()\n",
    "print(type(NonZero(-12)))\n",
    "print(type(NonZero(0)))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}